package com.vca.service.service.Impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.vca.common.constants.Constants;
import com.vca.common.constants.OrderRedisConstans;
import com.vca.common.exception.VcaException;
import com.vca.common.model.course.Course;
import com.vca.common.model.course.CourseScheduling;
import com.vca.common.model.exhibition.ExhibitionScheduling;
import com.vca.common.model.order.StoreOrder;
import com.vca.common.model.order.StoreOrderInfo;
import com.vca.common.model.sms.SmsTemplate;
import com.vca.common.model.system.SystemAdmin;
import com.vca.common.model.system.SystemNotification;
import com.vca.common.model.talk.Talk;
import com.vca.common.model.talk.TalkScheduling;
import com.vca.common.model.user.User;
import com.vca.common.model.user.UserToken;
import com.vca.common.page.CommonPage;
import com.vca.common.request.OrderWriteOffRequest;
import com.vca.common.request.PageParamRequest;
import com.vca.common.request.StoreOrderStaticsticsRequest;
import com.vca.common.request.WriteOffRecordRequest;
import com.vca.common.response.StoreOrderVerificationConfirmResponse;
import com.vca.common.response.StoreStaffDetail;
import com.vca.common.response.StoreStaffTopDetail;
import com.vca.common.response.WriteOffRecordResponse;
import com.vca.common.utils.*;
import com.vca.common.vo.*;
import com.vca.service.dao.order.StoreOrderDao;
import com.vca.service.dao.order.StoreOrderInfoDao;
import com.vca.service.dao.system.SystemAdminDao;
import com.vca.service.dao.user.UserDao;
import com.vca.service.delete.OrderUtils;
import com.vca.service.service.*;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.support.TransactionTemplate;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * StoreOrderVerificationImpl 接口实现 核销订单
 */
@Service
public class StoreOrderVerificationImpl implements StoreOrderVerification {

    @Resource
    private StoreOrderDao dao;

    @Resource
    private StoreOrderInfoDao storeOrderInfoDao;

    @Resource
    private StoreOrderStatusService storeOrderStatusService;

    @Autowired
    private OrderUtils orderUtils;

    @Autowired
    private StoreOrderService storeOrderService;

    @Autowired
    private StoreOrderInfoService storeOrderInfoService;

    @Autowired
    private TransactionTemplate transactionTemplate;

    @Autowired
    private RedisUtil redisUtil;

    @Resource
    private UserDao userDao;

    @Resource
    private SystemAdminDao systemAdminDao;

    @Autowired
    private SystemConfigService systemConfigService;

    @Autowired
    private CourseSchedulingService courseSchedulingService;

    @Autowired
    private TalkSchedulingService talkSchedulingService;

    @Autowired
    private ExhibitionSchedulingService exhibitionSchedulingService;

    @Autowired
    private SystemNotificationService systemNotificationService;

    @Autowired
    private CourseService courseService;

    @Autowired
    private UserTokenService userTokenService;

    @Autowired
    private TemplateMessageService templateMessageService;

    @Autowired
    private EmailTemplateService emailTemplateService;

    @Autowired
    private SmsTemplateService smsTemplateService;

    @Autowired
    private UserService userService;

    @Autowired
    private SmsService smsService;

    @Autowired
    private OrderPayService orderPayService;

    @Autowired
    private TalkService talkService;

    @Autowired
    private RedissonClient redissonClient;

    /**
     * 获取订单核销数据
     */
    @Override
    public StoreStaffTopDetail getOrderVerificationData() {
        StoreStaffTopDetail storeStaffTopDetail = new StoreStaffTopDetail();
        //订单支付没有退款 数量-
        LambdaQueryWrapper<StoreOrder> lqwOrderCount = Wrappers.lambdaQuery();
        lqwOrderCount.eq(StoreOrder::getIsDel, false).eq(StoreOrder::getPaid, true).eq(StoreOrder::getRefundStatus, 0);
        storeStaffTopDetail.setOrderCount(dao.selectCount(lqwOrderCount));
        //订单支付没有退款 支付总金额
        LambdaQueryWrapper<StoreOrder> lqwSumPrice = Wrappers.lambdaQuery();
        lqwSumPrice.eq(StoreOrder::getIsDel, false).eq(StoreOrder::getPaid, true).eq(StoreOrder::getRefundStatus, 0);
        List<StoreOrder> storeOrdersSumPrice = dao.selectList(lqwSumPrice);
        Double sumPrice = storeOrdersSumPrice.stream().mapToDouble(e -> e.getPayPrice().doubleValue()).sum();
        storeStaffTopDetail.setSumPrice(BigDecimal.valueOf(sumPrice).setScale(2, BigDecimal.ROUND_HALF_UP));
        //订单待支付 数量
        LambdaQueryWrapper<StoreOrder> lqwUnPaidCount = Wrappers.lambdaQuery();
        orderUtils.statusApiByWhere(lqwUnPaidCount, 0);
        storeStaffTopDetail.setUnpaidCount(dao.selectCount(lqwUnPaidCount));
        //订单待发货 数量
        LambdaQueryWrapper<StoreOrder> lqwUnShippedCount = Wrappers.lambdaQuery();
        orderUtils.statusApiByWhere(lqwUnShippedCount, 1);
        storeStaffTopDetail.setUnshippedCount(dao.selectCount(lqwUnShippedCount));
        //订单待收货 数量
        LambdaQueryWrapper<StoreOrder> lqwReceivedCount = Wrappers.lambdaQuery();
        orderUtils.statusApiByWhere(lqwReceivedCount, 2);
        storeStaffTopDetail.setReceivedCount(dao.selectCount(lqwReceivedCount));
        // 订单待核销数量
        LambdaQueryWrapper<StoreOrder> verificationCount = Wrappers.lambdaQuery();
        orderUtils.statusApiByWhere(verificationCount, 3);
        storeStaffTopDetail.setVerificationCount(dao.selectCount(verificationCount));
        //订单已完成 数量
        LambdaQueryWrapper<StoreOrder> lqwCompleteCount = Wrappers.lambdaQuery();
        orderUtils.statusApiByWhere(lqwCompleteCount, 4);
        storeStaffTopDetail.setCompleteCount(dao.selectCount(lqwCompleteCount));
        //订单退款 数量
        LambdaQueryWrapper<StoreOrder> lqwRefundCount = Wrappers.lambdaQuery();
        orderUtils.statusApiByWhere(lqwRefundCount, -3);
        storeStaffTopDetail.setRefundCount(dao.selectCount(lqwRefundCount));

        // 获取今日，昨日，本月，订单金额
        String dayStart = DateUtil.nowDateTime(Constants.DATE_FORMAT_START);
        String dayEnd = DateUtil.nowDateTime(Constants.DATE_FORMAT_END);
        String yesterdayStart = DateUtil.addDay(dayStart, -1, Constants.DATE_FORMAT_START);
        String yesterdayEnd = DateUtil.addDay(dayEnd, -1, Constants.DATE_FORMAT_END);
        String monthStart = DateUtil.nowDateTime(Constants.DATE_FORMAT_MONTH_START);
        String monthEnd = DateUtil.getMonthEndDay();

        // 今日订单数量
        LambdaQueryWrapper<StoreOrder> lqwTodayCount = Wrappers.lambdaQuery();
        lqwTodayCount.eq(StoreOrder::getIsDel, false).between(StoreOrder::getPayTime, dayStart, dayEnd)
                .eq(StoreOrder::getPaid, 1).eq(StoreOrder::getRefundStatus, 0);
        List<StoreOrder> storeOrdersTodayCount = dao.selectList(lqwTodayCount);
        if (null == storeOrdersTodayCount) storeOrdersTodayCount = new ArrayList<>();
        storeStaffTopDetail.setTodayCount(storeOrdersTodayCount.size());

        // 今日成交额
        double todayPrice = storeOrdersTodayCount.stream().mapToDouble(e -> e.getPayPrice().doubleValue()).sum();
        storeStaffTopDetail.setTodayPrice(BigDecimal.valueOf(todayPrice).setScale(2, BigDecimal.ROUND_HALF_UP));

        // 昨日订单数
        LambdaQueryWrapper<StoreOrder> lqwPro = Wrappers.lambdaQuery();
        lqwPro.eq(StoreOrder::getIsDel, false).between(StoreOrder::getCreateTime, yesterdayStart, yesterdayEnd)
                .eq(StoreOrder::getPaid, true).eq(StoreOrder::getRefundStatus, 0);
        List<StoreOrder> storeOrdersPro = dao.selectList(lqwPro);
        if (null == storeOrdersPro) storeOrdersPro = new ArrayList<>();
        storeStaffTopDetail.setProCount(storeOrdersPro.size());

        //  昨日成交额
        double proPrice = storeOrdersPro.stream().mapToDouble(e -> e.getPayPrice().doubleValue()).sum();
        storeStaffTopDetail.setProPrice(BigDecimal.valueOf(proPrice).setScale(2, BigDecimal.ROUND_HALF_UP));

        // 本月成交订单数量
        LambdaQueryWrapper<StoreOrder> lqwMonth = Wrappers.lambdaQuery();
        lqwMonth.eq(StoreOrder::getIsDel, false).between(StoreOrder::getPayTime, monthStart, monthEnd)
                .eq(StoreOrder::getPaid, true).eq(StoreOrder::getRefundStatus, 0);
        List<StoreOrder> storeOrdersMonth = dao.selectList(lqwMonth);
        if (null == storeOrdersMonth) storeOrdersMonth = new ArrayList<>();
        storeStaffTopDetail.setMonthCount(storeOrdersMonth.size());

        // 本月成交额
        double monthTotalPrice = storeOrdersMonth.stream().mapToDouble(e -> e.getPayPrice().doubleValue()).sum();
        storeStaffTopDetail.setMonthPrice(BigDecimal.valueOf(monthTotalPrice).setScale(2, BigDecimal.ROUND_HALF_UP));

        return storeStaffTopDetail;
    }

    /**
     * 核销月详情
     *
     * @return 月详情
     */
    @Override
    public List<StoreStaffDetail> getOrderVerificationDetail(StoreOrderStaticsticsRequest request) {
        request.setPage((request.getPage() - 1) * request.getLimit());
        dateLimitUtilVo dateLimit = DateUtil.getDateLimit(request.getDateLimit());
        request.setStartTime(dateLimit.getStartTime());
        request.setEndTime(dateLimit.getEndTime());
        return dao.getOrderVerificationDetail(request);
    }


    /**
     * 根据核销码核销订单(相当于收货)
     *
     * @return 核销结果
     */
    @Override
    public Boolean verificationOrderByCode(Integer id) {
        Boolean saveStatus = false;

        String lockKey = "StoreOrderInfo:"+id;
        RLock lock = redissonClient.getLock(lockKey);

        try {
            lock.lock(20L, TimeUnit.SECONDS);

            //订单详情信息
            LambdaQueryWrapper<StoreOrderInfo> storeOrderInfoLambdaQueryWrapper = new LambdaQueryWrapper<>();
            storeOrderInfoLambdaQueryWrapper.eq(StoreOrderInfo::getId, id);
            StoreOrderInfo storeOrderInfo = storeOrderInfoService.getOne(storeOrderInfoLambdaQueryWrapper);
            if (ObjectUtil.isNull(storeOrderInfo)) {
                throw new VcaException("订单不存在");
            }
            if(storeOrderInfo.getStatus().equals(Constants.ORDER_STATUS_INT_BARGAIN)) {
                throw new VcaException("该订单已经核销，请勿重复操作!");
            }

            LambdaQueryWrapper<StoreOrder> storeOrderLambdaQueryWrapper = new LambdaQueryWrapper<>();
            storeOrderLambdaQueryWrapper.eq(StoreOrder::getOrderId, storeOrderInfo.getOrderNo());
            StoreOrder storeOrder = storeOrderService.getOne(storeOrderLambdaQueryWrapper);

            //核销人员信息
            LoginUserVo loginUserVo = SecurityUtil.getLoginUserVo();
            SystemAdmin currentAdmin = loginUserVo.getUser();


            saveStatus = transactionTemplate.execute(e -> {
                storeOrderInfo.setStatus(Constants.ORDER_STATUS_INT_BARGAIN);
                storeOrderInfo.setWriteOffClerkId(currentAdmin.getId());
                storeOrderInfo.setWriteOffTime(new Date());
                storeOrderInfoService.updateById(storeOrderInfo);
                if (getIsStatusAll(storeOrder.getOrderId())) {
                    storeOrder.setStatus(Constants.ORDER_STATUS_INT_BARGAIN);
                    storeOrder.setUpdateTime(new Date());
                    dao.updateById(storeOrder);
                }
                storeOrderStatusService.createLog(storeOrder.getId(), Constants.ORDER_LOG_HEXIAO, 0, "核销完成");
                return Boolean.TRUE;
            });


            // 小程序订阅消息发送
            if (saveStatus) {//todo
                Boolean b = false;
                if (storeOrderInfo.getType().equals(0) || storeOrderInfo.getType().equals(1)) {
                    CourseScheduling courseScheduling = courseSchedulingService.getById(storeOrderInfo.getSchedulingId());
                    //用户购买 外部人数
                    if (storeOrder.getUserType().equals(0)) {
                        courseScheduling.setExternalStudentsNumber(courseScheduling.getExternalStudentsNumber() + 1);
                        b = courseSchedulingService.updateById(courseScheduling);
                    }
                    //后台赠送 内部人数
                    if (storeOrder.getUserType().equals(1)) {
                        courseScheduling.setInternalStudentsNumber(courseScheduling.getInternalStudentsNumber() + 1);
                        b = courseSchedulingService.updateById(courseScheduling);
                    }
                }

                if (storeOrderInfo.getType().equals(2)) {
                    TalkScheduling talkScheduling = talkSchedulingService.getById(storeOrderInfo.getSchedulingId());
                    talkScheduling.setNumberOfParticipants(talkScheduling.getNumberOfParticipants() + 1);
                    b = talkSchedulingService.updateById(talkScheduling);
                }
                if (storeOrderInfo.getType().equals(3)) {
                    ExhibitionScheduling exhibitionScheduling = exhibitionSchedulingService.getById(storeOrderInfo.getSchedulingId());
                    exhibitionScheduling.setNumberOfParticipants(exhibitionScheduling.getNumberOfParticipants() + 1);
                    b = exhibitionSchedulingService.updateById(exhibitionScheduling);
                }

                //后续操作放入redis
                orderVerification(storeOrderInfo);//todo  消息通知
                if (!b){
                    throw new VcaException("核销完成，参与人数变更失败");
                }
            }
        }finally {
            lock.unlock();
        }

        return saveStatus;
    }


    /**
     * 订单核销消息通知
     * @param storeOrderInfo
     * @return
     */
    public Boolean orderVerification(StoreOrderInfo storeOrderInfo) {
        StoreOrder storeOrder = storeOrderService.getByOrderId(storeOrderInfo.getOrderNo());
        SystemNotification paySuccessOfEvent = systemNotificationService.getByMark(OrderRedisConstans.WRITE_OFF_OF_EVENT);
        String name = "";
        if (storeOrderInfo.getType().equals(1)){
            Course course = courseService.getById(storeOrderInfo.getTaokeAboutCourseId());
            name = course.getName();
        }else {
            name = storeOrderInfo.getName();
        }
        if (paySuccessOfEvent.getIsRoutine().equals(1)) {
            // TODO: 2022/12/30 生成小程序订阅消息
            // 活动名称{{thing1.DATA}}活动时间{{time2.DATA}}签到时间段{{time3.DATA}}温馨提示{{thing5.DATA}}
            HashMap<String, String> messageMap = new HashMap<>();
            messageMap.put("thing1", name);
            messageMap.put("time2", storeOrderInfo.getSchedulingDate() +" " + storeOrderInfo.getSchedulingStartTime());
            messageMap.put("time3", cn.hutool.core.date.DateUtil.format(storeOrderInfo.getWriteOffTime(), Constants.DATE_FORMAT));
            messageMap.put("thing5", "已完成签到，愿您享受美妙的珠宝艺术之旅。");

            messageRoutineNotProduct(messageMap, storeOrderInfo,paySuccessOfEvent.getRoutineId());
        }
        if (paySuccessOfEvent.getIsWechat().equals(1)) {
            // TODO: 2023/1/3 公众号模板消息
            //{{first.DATA}}活动名称：{{keyword1.DATA}}活动地点：{{keyword2.DATA}}活动时间：{{keyword3.DATA}}{{remark.DATA}}
            HashMap<String,Object> message = new HashMap<>();
            message.put("first","活动签到提醒");
            message.put("keyword1",name);
            String addres = "";
            if (storeOrder.getUserType().equals(1)) {
                GenerateHelpVo.Info info = JSONObject.parseObject(storeOrderInfo.getInfo(),GenerateHelpVo.Info.class);
                addres = info.getCourseAddress().get("courseAddress") +""+info.getCourseAddress().get("courseAddressInfo")+""+info.getCourseAddress().get("dest");
            }else {
                PreOrderCommonVo.CourseInfoDetail courseInfoDetail = JSONObject.parseObject(storeOrderInfo.getInfo(), PreOrderCommonVo.CourseInfoDetail.class);
                for (PreOrderCommonVo.CourseInfoDetail.Scheduling scheduling : courseInfoDetail.getSchedulings()) {
                    if (scheduling.getScheduleId().equals(storeOrderInfo.getSchedulingId())){
                        addres = scheduling.getCourseAddress().get("courseAddress")+""+scheduling.getCourseAddress().get("courseAddressInfo")+""+scheduling.getCourseAddress().get("dest");
                    }
                }
            }

            message.put("keyword2",addres);
            message.put("keyword3",storeOrderInfo.getSchedulingDate() +" " + storeOrderInfo.getSchedulingStartTime());
            message.put("remark","请留意活动时间，感谢您的参与！");
            orderVerificationByPublicAccount(message,paySuccessOfEvent.getWechatId(),storeOrderInfo);
        }
        if (paySuccessOfEvent.getIsSms().equals(1)) {
            // TODO: 2023/1/3 发送短信
            SmsTemplate smsTemplate = smsTemplateService.getDetail(paySuccessOfEvent.getSmsId());
            if (Objects.equals(storeOrderInfo.getBuyer(), storeOrderInfo.getLecturer())) {
                smsOrderVerification(storeOrderInfo.getBuyer(),name,storeOrderInfo,smsTemplate.getTempId());
            } else {
                smsOrderVerification(storeOrderInfo.getBuyer(),name,storeOrderInfo,smsTemplate.getTempId());
                smsOrderVerification(storeOrderInfo.getLecturer(),name,storeOrderInfo,smsTemplate.getTempId());

            }
        }
        return Boolean.TRUE;
    }

    /**
     * 订单核销订阅号消息模板
     * @param messageMap
     * @param storeOrderInfo
     * @param routineId
     */
    public void messageRoutineNotProduct(HashMap<String, String> messageMap, StoreOrderInfo storeOrderInfo, Integer routineId) {

        UserToken buyerToken = new UserToken();
        if (ObjectUtil.isNotNull(storeOrderInfo.getBuyer())) {
            buyerToken = userTokenService.getTokenByUserId(storeOrderInfo.getBuyer(), OrderRedisConstans.SYSTEM_TYPE_ROUTINE);
        }
        UserToken lecturerToken = new UserToken();
        if (ObjectUtil.isNotNull(storeOrderInfo.getLecturer())) {
            lecturerToken = userTokenService.getTokenByUserId(storeOrderInfo.getLecturer(), OrderRedisConstans.SYSTEM_TYPE_ROUTINE);
        }
        if (Objects.equals(storeOrderInfo.getBuyer(), storeOrderInfo.getLecturer())) {
            if (ObjectUtil.isNotNull(buyerToken)) {
                templateMessageService.pushMiniTemplateMessage(routineId, messageMap, buyerToken.getToken(), "pages/user-order-details/index?orderNo="+storeOrderInfo.getOrderNo());
            }
        } else {
            if (ObjectUtil.isNotNull(buyerToken)) {
                templateMessageService.pushMiniTemplateMessage(routineId, messageMap, buyerToken.getToken(), "pages/user-order-details/index?orderNo="+storeOrderInfo.getOrderNo());
            }
            if (ObjectUtil.isNotNull(lecturerToken)) {
                templateMessageService.pushMiniTemplateMessage(routineId, messageMap, lecturerToken.getToken(), "pages/user-order-details/index?orderNo="+storeOrderInfo.getOrderNo());
            }
        }
    }

    private void orderVerificationByPublicAccount(HashMap<String,Object> message,Integer wechatId, StoreOrderInfo storeOrderInfo){

        String pageUrl = "pages/user-order-details/index?orderNo="+storeOrderInfo.getOrderNo();
        UserToken buyerToken = new UserToken();
        if (ObjectUtil.isNotNull(storeOrderInfo.getBuyer())) {
            buyerToken = userTokenService.getTokenByUserId(storeOrderInfo.getBuyer(), OrderRedisConstans.SYSTEM_TYPE_ROUTINE);
        }
        UserToken lecturerToken = new UserToken();
        if (ObjectUtil.isNotNull(storeOrderInfo.getLecturer())) {
            lecturerToken = userTokenService.getTokenByUserId(storeOrderInfo.getLecturer(), OrderRedisConstans.SYSTEM_TYPE_ROUTINE);
        }
        if (Objects.equals(storeOrderInfo.getBuyer(), storeOrderInfo.getLecturer())) {
            if (ObjectUtil.isNotNull(buyerToken)) {
                templateMessageService.pushTemplatePublicMessage(pageUrl,wechatId, message, buyerToken.getToken());
            }
        } else {
            if (ObjectUtil.isNotNull(buyerToken)) {
                templateMessageService.pushTemplatePublicMessage(pageUrl, wechatId, message, buyerToken.getToken());
            }
            if (ObjectUtil.isNotNull(lecturerToken)) {
                templateMessageService.pushTemplatePublicMessage(pageUrl, wechatId, message, lecturerToken.getToken());
            }
        }
    }

    /**
     * 订单核销短信模板
     * @param userId
     * @param name
     * @param orderInfo
     * @param tempId
     */
    private void smsOrderVerification(Integer userId, String name, StoreOrderInfo orderInfo, String tempId) {
        String pageUrl = "pages/user-order-details/index?orderNo="+orderInfo.getOrderNo();
        if (ObjectUtil.isNotNull(userId)) {
            User user = userService.getById(userId);
            if (ObjectUtil.isNotNull(user.getPhone())) {
                smsService.sendOrderWriteOff(name, user.getPhone(), tempId,pageUrl);
            }
        } else {
            smsService.sendOrderWriteOff(name, orderInfo.getLecturerPhone(), tempId, pageUrl);
        }
    }

    /**
     * 判断是否所有订单都核销完成
     * @param orderNo
     * @return
     */
    public Boolean getIsStatusAll(String orderNo) {
        //全部订单
        List<StoreOrderInfo> statustList = storeOrderInfoService.list(new LambdaQueryWrapper<StoreOrderInfo>().eq(StoreOrderInfo::getOrderNo, orderNo));
        //已核销订单
        List<StoreOrderInfo> allList = storeOrderInfoService.list(new LambdaQueryWrapper<StoreOrderInfo>().eq(StoreOrderInfo::getOrderNo, orderNo).eq(StoreOrderInfo::getStatus, 2));

        //如果全部订单数量和已核销订单数量相同则为已全部核销
        if (statustList.size() == allList.size()) {
            return true;
        }
        return false;
    }

    /**
     * 根据核销码查询待核销订单
     *
     * @return 待核销订单详情
     */
    @Override
    public StoreOrderVerificationConfirmResponse getVerificationOrderByCode(OrderWriteOffRequest request, PageParamRequest pageParamRequest) {

        User user = new User();
        List<OrderWriteOff> orderWriterOffs = new ArrayList<>();
        if (StringUtils.isNotBlank(request.getQrCode())) {// 核销码解密
            String qrCode = MiracleAECUtil.decrypt(request.getQrCode());
            Map<String, String> map = analysisQrCode(qrCode);
            //判断是否为小程序端并且时间是否超过24小时
            if (map.get("channel").equals("wechat")) {
                Boolean time = isOvertime(map.get("time"));
                if (!time) {
                    throw new VcaException("二维码已过期");
                }
            }

            Integer userId = Integer.valueOf(map.get("userid"));
            LambdaQueryWrapper<User> userLambdaQueryWrapper = new LambdaQueryWrapper();
            userLambdaQueryWrapper.eq(User::getStatus, 1);
            userLambdaQueryWrapper.eq(User::getUid, userId);
            user = userDao.selectOne(userLambdaQueryWrapper);
        }
        if (StringUtils.isNotBlank(request.getUserPhoneOrEmail())) {
            LambdaQueryWrapper<User> userLambdaQueryWrapper = new LambdaQueryWrapper();
            userLambdaQueryWrapper.eq(User::getStatus, 1);
            userLambdaQueryWrapper.eq(User::getPhone, request.getUserPhoneOrEmail()).or().eq(User::getEmail, request.getUserPhoneOrEmail());
            user = userDao.selectOne(userLambdaQueryWrapper);
        }

        if (ObjectUtil.isNull(user)) {
            throw new VcaException("该用户不存在");
        }
        StoreOrderVerificationConfirmResponse response = new StoreOrderVerificationConfirmResponse();

//        LambdaQueryWrapper<StoreOrderInfo> storeOrderInfoLambdaQueryWrapper = new LambdaQueryWrapper<>();
//        storeOrderInfoLambdaQueryWrapper.eq(StoreOrderInfo::getLecturer, user.getUid());
        List<StoreOrderInfo> storeOrderInfoList = new ArrayList<>();
        if (request.getType().equals(0)) {
//            storeOrderInfoLambdaQueryWrapper.in(StoreOrderInfo::getType, 0, 1);
            ArrayList<Integer> type = new ArrayList<>();
            type.add(0);
            type.add(1);
            if (StringUtils.isNotBlank(request.getDateLimit())) {
                dateLimitUtilVo dateLimitUtilVo = DateUtil.getDateLimit(request.getDateLimit());
//                storeOrderInfoLambdaQueryWrapper.between(StoreOrderInfo::getSchedulingDate, dateLimitUtilVo.getStartTime().substring(0, 10), dateLimitUtilVo.getEndTime().substring(0, 10));
                storeOrderInfoList = storeOrderInfoDao.getWriterOffOrder(user.getUid(),type,dateLimitUtilVo.getStartTime().substring(0, 10), dateLimitUtilVo.getEndTime().substring(0, 10));
            }else {
                storeOrderInfoList = storeOrderInfoDao.getWriterOffOrder(user.getUid(),type,null, null);
            }

        } else {
            ArrayList<Integer> type = new ArrayList<>();
            type.add(request.getType());
            if (StringUtils.isNotBlank(request.getDateLimit())) {
                dateLimitUtilVo dateLimitUtilVo = DateUtil.getDateLimit(request.getDateLimit());
//                storeOrderInfoLambdaQueryWrapper.between(StoreOrderInfo::getSchedulingDate, dateLimitUtilVo.getStartTime().substring(0, 10), dateLimitUtilVo.getEndTime().substring(0, 10));
                storeOrderInfoList = storeOrderInfoDao.getWriterOffOrder(user.getUid(),type,dateLimitUtilVo.getStartTime().substring(0, 10), dateLimitUtilVo.getEndTime().substring(0, 10));
            }else {
                storeOrderInfoList = storeOrderInfoDao.getWriterOffOrder(user.getUid(), type, null, null);
            }
        }


//        storeOrderInfoLambdaQueryWrapper.eq(StoreOrderInfo::getStatus, 1);
//        storeOrderInfoLambdaQueryWrapper.eq(StoreOrderInfo::getRefundStatus, 0);
//        storeOrderInfoLambdaQueryWrapper.eq(StoreOrderInfo::getIsGet, 1);
//        List<StoreOrderInfo> storeOrderInfoList = storeOrderInfoService.list(storeOrderInfoLambdaQueryWrapper);
        List<OrderWriteOff> removeList = new ArrayList<>();
        for (StoreOrderInfo storeOrderInfo : storeOrderInfoList) {
            OrderWriteOff orderWriteOff = new OrderWriteOff();
            BeanUtils.copyProperties(storeOrderInfo, orderWriteOff);
            PreOrderCommonVo.CourseInfoDetail info = JSONObject.parseObject(storeOrderInfo.getInfo(), PreOrderCommonVo.CourseInfoDetail.class);
            if (storeOrderInfo.getType().equals(1)) {
                for (PreOrderCommonVo.CourseInfoDetail.Scheduling scheduling : info.getSchedulings()) {
                    if (scheduling.getCourseId().equals(storeOrderInfo.getTaokeAboutCourseId())) {
                        orderWriteOff.setName(scheduling.getCourseName());
                    }
                }
            } else {
                orderWriteOff.setName(info.getName());
            }

            orderWriterOffs.add(orderWriteOff);
        }

        //讲座删除线上讲座
        if (request.getType().equals(2)){
            if (CollUtil.isNotEmpty(orderWriterOffs)){
                for (OrderWriteOff orderWriterOff : orderWriterOffs) {
                    if (orderWriterOff.getType().equals(2)){ //删除线上讲座
                        Talk talk = talkService.getById(orderWriterOff.getMainId());
                        if (ObjectUtil.isNull(talk)){
                            throw new VcaException("讲座不存在");
                        }
                        if (talk.getTalkType().equals(2)){
                            removeList.add(orderWriterOff);
                        }
                    }
                }
                orderWriterOffs.removeAll(removeList);
            }

        }

        PageInfo<OrderWriteOff> orderWriteOffPageInfo = PageUtils.startPage(orderWriterOffs, pageParamRequest.getPage(), pageParamRequest.getLimit());
        BeanUtils.copyProperties(user, response);
        response.setUserPhone(user.getPhone());
        response.setOrderWriteOffs(orderWriteOffPageInfo);
        return response;
    }

    /**
     * @Description: 核销记录列表
     * @Author: xyg
     * @Date: 2022/11/29
     */
    @Override
    public CommonPage<WriteOffRecordResponse> getWriteOffRecordList(WriteOffRecordRequest request, PageParamRequest pageParamRequest) {
        Page<Object> startPage = PageHelper.startPage(pageParamRequest.getPage(), pageParamRequest.getLimit());
        //根据条件查询
        List<WriteOffRecordResponse> writerOffInfo = new ArrayList<>();

        if (StringUtils.isNotBlank(request.getDateLimit()) && StringUtils.isNotBlank(request.getSchedulingDate())) {
            dateLimitUtilVo dateLimitUtilVo = DateUtil.getDateLimit(request.getDateLimit());
            String[] split = request.getSchedulingDate().split(",");
            String schedulingDateStart = split[0];
            String schedulingDateEnd = split[0];
            writerOffInfo = storeOrderInfoDao.getWriterOffInfo(dateLimitUtilVo.getStartTime(), dateLimitUtilVo.getEndTime(),
                    request.getOrderNo(), request.getProductName(), request.getLecturerPhone(), request.getRealName(),
                    schedulingDateStart, schedulingDateEnd, request.getType());
        } else if (StringUtils.isNotBlank(request.getDateLimit())) {
            dateLimitUtilVo dateLimitUtilVo = DateUtil.getDateLimit(request.getDateLimit());
            writerOffInfo = storeOrderInfoDao.getWriterOffInfo(dateLimitUtilVo.getStartTime(), dateLimitUtilVo.getEndTime(),
                    request.getOrderNo(), request.getProductName(), request.getLecturerPhone(), request.getRealName(),
                    null, null, request.getType());
        } else if (StringUtils.isNotBlank(request.getSchedulingDate())) {
            String[] split = request.getSchedulingDate().split(",");
            String schedulingDateStart = split[0];
            String schedulingDateEnd = split[0];
            writerOffInfo = storeOrderInfoDao.getWriterOffInfo(null, null,
                request.getOrderNo(), request.getProductName(), request.getLecturerPhone(), request.getRealName(),
                schedulingDateStart, schedulingDateEnd, request.getType());
        } else {
            writerOffInfo = storeOrderInfoDao.getWriterOffInfo(null, null,
                    request.getOrderNo(), request.getProductName(), request.getLecturerPhone(), request.getRealName(),
                    null, null, request.getType());
        }
        //获取所有核销员id
        List<Integer> writeOffClerkIdList = writerOffInfo.stream().map(WriteOffRecordResponse::getWriteOffClerkId).distinct().collect(Collectors.toList());
        HashMap<Integer, String> writeOffClerk = getWriteOffClerk(writeOffClerkIdList);
        //把info的商品名称 和核销员名称查询并更新
        for (WriteOffRecordResponse writeOffRecordResponse : writerOffInfo) {
            writeOffRecordResponse.setWriteOffClerkName(writeOffClerk.get(writeOffRecordResponse.getWriteOffClerkId()));
            GenerateHelpVo.Info info = JSON.parseObject(writeOffRecordResponse.getInfo(), GenerateHelpVo.Info.class);
            writeOffRecordResponse.setInfo(info.getName());
            writeOffRecordResponse.setCoverImage(info.getCoverImage());
        }


        return CommonPage.restPage(CommonPage.copyPageInfo(startPage, writerOffInfo));
    }

    /**
     * @Description: 根据核销员id获取map
     * @Author: xyg
     * @Date: 2022/11/29
     */
    public HashMap<Integer, String> getWriteOffClerk(List<Integer> writeOffClerkIdList) {
        HashMap<Integer, String> map = new HashMap<>();
        if (writeOffClerkIdList.size() < 1) {
            return map;
        }
        LambdaQueryWrapper<SystemAdmin> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.in(SystemAdmin::getId, writeOffClerkIdList);
        lambdaQueryWrapper.eq(SystemAdmin::getStatus, 1);
        lambdaQueryWrapper.eq(SystemAdmin::getIsDel, 0);
        List<SystemAdmin> systemAdmins = systemAdminDao.selectList(lambdaQueryWrapper);
        if (systemAdmins.size() < 1) {
            return map;
        }
        for (SystemAdmin systemAdmin : systemAdmins) {
            map.put(systemAdmin.getId(), systemAdmin.getRealName());
        }
        return map;
    }

    /**
     * @Description: 判断时间是否超过二十四小时
     * @Author: xyg
     * @Date: 2022/11/30
     */
    public Boolean isOvertime(String time) {
        Integer qrcode_period = Integer.valueOf(systemConfigService.getValueByKey("qrcode_period"));
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-M-d HH:mm:ss");
        String currentTime = sdf.format(new Date());
        Date start = null;//业务时间
        Date end = null;//当前时间
        try {
            start = sdf.parse(sdf.format(new Date(Long.parseLong(time))));//业务时间
            end = sdf.parse(currentTime);//当前时间
        } catch (ParseException e) {
            e.printStackTrace();
        }
        long cha = end.getTime() - start.getTime();
        if (cha < 0) {
            return false;
        }
        double result = cha * 1.0 / (1000 * 60 * 60);

        if (result <= qrcode_period) {
            return true;
        } else {
            return false;
        }
    }

    public Map<String, String> analysisQrCode(String qrCode) {
        HashMap<String, String> map = new HashMap<>();
        List<String> strings = Arrays.asList(qrCode.split("&"));
        strings.forEach(s -> {
            List<String> stringList = Arrays.asList(s.split("="));
            String key = null;
            String value = null;
            for (int i = 0; i < stringList.size(); i++) {
                if (i == 0) {
                    key = stringList.get(i);
                }
                if (i == 1) {
                    value = stringList.get(i);
                }
            }
            map.put(key, value);
        });
        return map;
    }

}
